package com.citsin.atlas.viewmodel

import android.content.ContentResolver
import android.content.ContentUris
import android.provider.MediaStore
import androidx.paging.PositionalDataSource
import com.citsin.atlas.bean.Media
import java.lang.StringBuilder
import kotlin.collections.ArrayList

/**
 * citsin
 * 2019-06-03
 */
class MediaDataSource(
    private val contentResolver: ContentResolver,
    private val mediaTypes: Array<Int>,
    private val bucketId: String
) :
    PositionalDataSource<Media>() {
    companion object {
        private val QUERY_URI = MediaStore.Files.getContentUri("external")
    }

    override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<Media>) {
        callback.onResult(load(params.startPosition, params.loadSize))
    }

    override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<Media>) {
        callback.onResult(load(params.requestedStartPosition, params.requestedLoadSize), params.requestedStartPosition)
    }

    private fun load(startPosition: Int, loadSize: Int): MutableList<Media> {

        val projection = arrayOf(
            MediaStore.Files.FileColumns._ID,
            MediaStore.MediaColumns.DISPLAY_NAME,
            MediaStore.MediaColumns.MIME_TYPE,
            MediaStore.MediaColumns.SIZE,
            "duration"
        )

        val selection = StringBuilder()
        val isMediaTypesEmpty = mediaTypes.isNullOrEmpty()
        if (!isMediaTypesEmpty) {
            selection.append('(')
            val count = mediaTypes.size
            for ((index, _) in mediaTypes.withIndex()) {
                selection.append(MediaStore.Files.FileColumns.MEDIA_TYPE)
                selection.append("=?")
                if (index != count - 1) {
                    selection.append(" OR ")
                }
            }
            selection.append(") AND ")
        }
        selection.append(MediaStore.MediaColumns.SIZE)
        selection.append(">0  AND bucket_id=? ")
        val size = if (mediaTypes.isNullOrEmpty()) 1 else mediaTypes.size + 1

        val selectionArgs = ArrayList<String>(size)
        if (!isMediaTypesEmpty) {
            mediaTypes.forEach { type ->
                selectionArgs.add(type.toString())
            }
        }
        selectionArgs.add(bucketId)

        val bucketOrderBy = "datetaken DESC  limit $loadSize offset $startPosition"


        val cursor =
            contentResolver.query(QUERY_URI, projection, String(selection), selectionArgs.toTypedArray(), bucketOrderBy)
        val medias: MutableList<Media> = mutableListOf()
        if (cursor == null){
            return medias
        }
        while (cursor.moveToNext()) {
            val id = cursor.getString(0)
            val displayName = cursor.getString(1)
            val mediaType = cursor.getInt(2)
            val uri = ContentUris.withAppendedId(MediaStore.Files.getContentUri("external"),id.toLong())
            medias.add(Media(id, displayName, mediaType,uri.toString()))
        }
        return medias


    }
}